/**
 * 描述：TODO
 * 包名：com.casic.core.db.datasource
 */
package com.ccp.dev.core.basic.db.datasource;

import com.ccp.dev.core.basic.db.datasource.threadquery.QueryThread;
import com.ccp.dev.core.basic.mybatis.Dialect;
import com.ccp.dev.core.basic.page.PageBean;
import com.ccp.dev.core.basic.page.PageList;
import com.ccp.dev.core.basic.util.DialectUtil;
import com.ccp.dev.core.util.AppUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;


/**
 * <pre>
 * jdbc关于pagebean的查询！！！
 * 注意：里面的alias参数都是数据源的别名！！
 */
@Component
public class JdbcTemplateUtil {

    /**
     * 使用JdbcTemplate 执行SQL语句。
     *
     * @param sql
     */
    public static void execute(String sql) {
        JdbcTemplate jdbcTemplate = (JdbcTemplate) AppUtil.getBean("jdbcTemplate");
        jdbcTemplate.execute(sql);
    }

    /**
     * 使用JdbcTemplate执行外部SQL语句。
     *
     * @param dsName 数据源名称
     * @param sql    SQL语句
     * @throws Exception
     */
    public static void execute(String dsName, String sql) throws Exception {
        DataSource dataSource = DataSourceUtil.getDataSourceByAlias(dsName);
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        jdbcTemplate.execute(sql);
    }

    /**
     * 获取名称JdbcTemplate。
     *
     * <pre>
     * SQL语句使用下面模版的形式。
     * 执行类似的语句。
     * select * from test where name=:name;
     * Map<String, Object> paramMap = new HashMap<String, Object>();
     * paramMap.put("name", "name5");
     * </pre>
     *
     * @param jdbcTemplate
     * @return
     */
    public static NamedParameterJdbcTemplate getNamedParameterJdbcTemplate(JdbcTemplate jdbcTemplate) {
        return new NamedParameterJdbcTemplate(jdbcTemplate.getDataSource());
    }

    /**
     * 根据数据源别名获取NamedParameterJdbcTemplate对象。
     *
     * @param alias 数据源别名。
     * @return
     */
    public static NamedParameterJdbcTemplate getNamedParameterJdbcTemplate(String alias) {
        try {
            return new NamedParameterJdbcTemplate(DataSourceUtil.getDataSourceByAlias(alias));
        } catch (Exception e) {
            return null;
        }
    }

    public static JdbcTemplate getNewJdbcTemplate(String alias) throws Exception {
        Map<Object, Object> map = DataSourceUtil.getDataSources();
        DataSource ds = (DataSource) map.get(alias);
        return ds != null && !alias.equals("dataSource_Default") ? new JdbcTemplate(ds) : (JdbcTemplate) AppUtil.getBean("jdbcTemplate");
    }

    private static final Log logger = LogFactory.getLog(JdbcTemplateUtil.class);

    @Autowired
    private DialectUtil dialectUtil;

    public PageList getPage(String alias, int currentPage, int pageSize, String sql, Map paraMap) {
        int offset = (currentPage - 1) * pageSize;
        Dialect dialect;
        try {
            dialect = dialectUtil.getDialectByDataSourceAlias(alias);
        } catch (Exception e) {
            return null;
        }

        String pageSql = dialect.getDLimitString(sql, offset, pageSize);
        String totalSql = dialect.getCountSql(sql);
        NamedParameterJdbcTemplate namedParameterJdbcTemplate = getNamedParameterJdbcTemplate(alias);
        List list = new ArrayList();
        int total = 0;

        List<Callable<Map<String, Object>>> tasks = new ArrayList<Callable<Map<String, Object>>>();
        ExecutorService pool = Executors.newFixedThreadPool(2);
        logger.info("查询的SQL：" + pageSql);
        Callable<Map<String, Object>> dataQuery = new QueryThread(namedParameterJdbcTemplate, pageSql, paraMap, false);
        Callable<Map<String, Object>> countQuery = new QueryThread(namedParameterJdbcTemplate, totalSql, paraMap, true);
        tasks.add(dataQuery);
        tasks.add(countQuery);
        try {
            List<Future<Map<String, Object>>> futures = pool.invokeAll(tasks);
            if (futures != null && futures.size() > 0) {
                for (Future<Map<String, Object>> future : futures) {
                    if (future.get().get("list") != null) {
                        list = (List) future.get().get("list");
                    }
                    if (future.get().get("total") != null) {
                        total = (int) future.get().get("total");
                    }
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
            pool.shutdown();
        } catch (ExecutionException e) {
            e.printStackTrace();
            pool.shutdown();
        } finally {
//            pool.shutdown();
        }

        PageBean pageBean = new PageBean(currentPage, pageSize);
        pageBean.setTotalCount(total);
        PageList pageList = new PageList();
        pageList.addAll(list);
        pageList.setPageBean(pageBean);
        return pageList;
    }
}
